package com.flsldl.mydb.backend.dm.dataItem;

import com.flsldl.mydb.backend.common.SubArray;
import com.flsldl.mydb.backend.dm.DataManagerImpl;
import com.flsldl.mydb.backend.dm.page.Page;
import com.flsldl.mydb.backend.utils.Parser;
import com.flsldl.mydb.backend.utils.Types;
import com.google.common.primitives.Bytes;

import java.util.Arrays;

public interface DataItem {
    SubArray data();
    
    void before();
    void unBefore();
    void after(long xid);
    void release();

    void lock();
    void unlock();
    void rLock();
    void rUnLock();

    Page page();
    long getUid();
    byte[] getOldRaw();
    SubArray getRaw();

    // 包装原始数据为 dataitem 格式
    public static byte[] wrapDataItemRaw(byte[] raw) {
        // ValidFlag 占用 1 字节，标识了该 DataItem 是否有效
        byte[] valid = new byte[1];
        // DataSize 占用 2 字节，标识了后面 Data 的长度
        byte[] size = Parser.short2Byte((short)raw.length);
        return Bytes.concat(valid, size, raw);
    }

    // 从页面的 offset 处解析出 dataitem
    public static DataItem parseDataItem(Page pg, short offset, DataManagerImpl dm) {
        // 获取该页数据
        byte[] raw = pg.getData();
        // 获取对应下标下的 dataitem 的 size
        short size = Parser.parseShort(Arrays.copyOfRange(raw, offset+DataItemImpl.OF_SIZE, offset+DataItemImpl.OF_DATA));
        // 获取整个 dataitem 的长度
        short length = (short)(size + DataItemImpl.OF_DATA);
        // 将页码和对应页的下标位置拼接
        long uid = Types.addressToUid(pg.getPageNumber(), offset);
        // 新建共享内存数组，数据位置在 offset ~ offset + length 中
        return new DataItemImpl(new SubArray(raw, offset, offset+length), new byte[length], pg, uid, dm);
    }

    // 设置 dataitem 的有效性 更改 ValidFlag
    public static void setDataItemRawInvalid(byte[] raw) {
        raw[DataItemImpl.OF_VALID] = (byte)1;
    }
}
